using System.Runtime.InteropServices;
using UnityEngine;
using UnityEngine.Networking;

public class CharacterAnimation : NetworkBehaviour
{
	private Animator animator;

	public HumanBodyBones UpperChest = HumanBodyBones.UpperChest;

	public Transform headCamera;

	[HideInInspector]
	public Quaternion UpperBodyRotation;

	public BlendAxis Axis = BlendAxis.Z;

	public Vector3 Offset;

	public float Speed = -1f;

	private CharacterSystem character;

	[SyncVar]
	private float cameraRotationSync;

	private float timeTmpsending;

	private static int kCmdCmdCameraUpdate;

	public float NetworkcameraRotationSync
	{
		get
		{
			return cameraRotationSync;
		}
		[param: In]
		set
		{
			SetSyncVar(value, ref cameraRotationSync, 1u);
		}
	}

	private void Start()
	{
		animator = GetComponent<Animator>();
		character = GetComponent<CharacterSystem>();
		if (headCamera == null)
		{
			FPSCamera componentInChildren = GetComponentInChildren<FPSCamera>();
			headCamera = componentInChildren.gameObject.transform;
		}
	}

	[Command(channel = 1)]
	private void CmdCameraUpdate(float camRotaion)
	{
		NetworkcameraRotationSync = camRotaion;
	}

	private void Update()
	{
		if (animator == null || character == null)
		{
			return;
		}
		if (base.isLocalPlayer)
		{
			UpperBodyRotation = Quaternion.identity;
			Vector3 eulerAngles = headCamera.transform.localRotation.eulerAngles;
			float num = eulerAngles.x;
			if (character.MovementPreset.Length > character.MovementIndex)
			{
				num += character.MovementPreset[character.MovementIndex].UpperChestOffset;
			}
			switch (Axis)
			{
			case BlendAxis.X:
			{
				ref Quaternion upperBodyRotation3 = ref UpperBodyRotation;
				float x3 = Speed * num + Offset.x;
				Vector3 eulerAngles6 = UpperBodyRotation.eulerAngles;
				float y2 = eulerAngles6.y + Offset.y;
				Vector3 eulerAngles7 = UpperBodyRotation.eulerAngles;
				upperBodyRotation3.eulerAngles = new Vector3(x3, y2, eulerAngles7.z + Offset.z);
				break;
			}
			case BlendAxis.Y:
			{
				ref Quaternion upperBodyRotation2 = ref UpperBodyRotation;
				Vector3 eulerAngles4 = UpperBodyRotation.eulerAngles;
				float x2 = eulerAngles4.x + Offset.x;
				float y = Speed * num + Offset.y;
				Vector3 eulerAngles5 = UpperBodyRotation.eulerAngles;
				upperBodyRotation2.eulerAngles = new Vector3(x2, y, eulerAngles5.z + Offset.z);
				break;
			}
			case BlendAxis.Z:
			{
				ref Quaternion upperBodyRotation = ref UpperBodyRotation;
				Vector3 eulerAngles2 = UpperBodyRotation.eulerAngles;
				float x = eulerAngles2.x + Offset.x;
				Vector3 eulerAngles3 = UpperBodyRotation.eulerAngles;
				upperBodyRotation.eulerAngles = new Vector3(x, eulerAngles3.y + Offset.y, Speed * num + Offset.z);
				break;
			}
			}
			float num2 = 1f / Time.deltaTime;
			float num3 = num2 / character.currentSendingRate * Time.deltaTime;
			if (Time.time > timeTmpsending + num3)
			{
				CallCmdCameraUpdate(num);
				timeTmpsending = Time.time;
			}
		}
		else
		{
			Quaternion upperBodyRotation4 = UpperBodyRotation;
			switch (Axis)
			{
			case BlendAxis.X:
			{
				float x6 = Speed * cameraRotationSync + Offset.x;
				Vector3 eulerAngles12 = upperBodyRotation4.eulerAngles;
				float y4 = eulerAngles12.y + Offset.y;
				Vector3 eulerAngles13 = upperBodyRotation4.eulerAngles;
				upperBodyRotation4.eulerAngles = new Vector3(x6, y4, eulerAngles13.z + Offset.z);
				break;
			}
			case BlendAxis.Y:
			{
				Vector3 eulerAngles10 = upperBodyRotation4.eulerAngles;
				float x5 = eulerAngles10.x + Offset.x;
				float y3 = Speed * cameraRotationSync + Offset.y;
				Vector3 eulerAngles11 = upperBodyRotation4.eulerAngles;
				upperBodyRotation4.eulerAngles = new Vector3(x5, y3, eulerAngles11.z + Offset.z);
				break;
			}
			case BlendAxis.Z:
			{
				Vector3 eulerAngles8 = upperBodyRotation4.eulerAngles;
				float x4 = eulerAngles8.x + Offset.x;
				Vector3 eulerAngles9 = upperBodyRotation4.eulerAngles;
				upperBodyRotation4.eulerAngles = new Vector3(x4, eulerAngles9.y + Offset.y, Speed * cameraRotationSync + Offset.z);
				break;
			}
			}
			UpperBodyRotation = Quaternion.Lerp(UpperBodyRotation, upperBodyRotation4, 30f * Time.deltaTime);
		}
	}

	private void OnAnimatorIK(int layerIndex)
	{
		animator.SetBoneLocalRotation(UpperChest, UpperBodyRotation);
	}

	private void UNetVersion()
	{
	}

	protected static void InvokeCmdCmdCameraUpdate(NetworkBehaviour obj, NetworkReader reader)
	{
		if (!NetworkServer.active)
		{
			UnityEngine.Debug.LogError("Command CmdCameraUpdate called on client.");
		}
		else
		{
			((CharacterAnimation)obj).CmdCameraUpdate(reader.ReadSingle());
		}
	}

	public void CallCmdCameraUpdate(float camRotaion)
	{
		if (!NetworkClient.active)
		{
			UnityEngine.Debug.LogError("Command function CmdCameraUpdate called on server.");
			return;
		}
		if (base.isServer)
		{
			CmdCameraUpdate(camRotaion);
			return;
		}
		NetworkWriter networkWriter = new NetworkWriter();
		networkWriter.Write((short)0);
		networkWriter.Write((short)5);
		networkWriter.WritePackedUInt32((uint)kCmdCmdCameraUpdate);
		networkWriter.Write(GetComponent<NetworkIdentity>().netId);
		networkWriter.Write(camRotaion);
		SendCommandInternal(networkWriter, 1, "CmdCameraUpdate");
	}

	static CharacterAnimation()
	{
		kCmdCmdCameraUpdate = 1735055529;
		NetworkBehaviour.RegisterCommandDelegate(typeof(CharacterAnimation), kCmdCmdCameraUpdate, InvokeCmdCmdCameraUpdate);
		NetworkCRC.RegisterBehaviour("CharacterAnimation", 0);
	}

	public override bool OnSerialize(NetworkWriter writer, bool forceAll)
	{
		if (forceAll)
		{
			writer.Write(cameraRotationSync);
			return true;
		}
		bool flag = false;
		if ((base.syncVarDirtyBits & 1) != 0)
		{
			if (!flag)
			{
				writer.WritePackedUInt32(base.syncVarDirtyBits);
				flag = true;
			}
			writer.Write(cameraRotationSync);
		}
		if (!flag)
		{
			writer.WritePackedUInt32(base.syncVarDirtyBits);
		}
		return flag;
	}

	public override void OnDeserialize(NetworkReader reader, bool initialState)
	{
		if (initialState)
		{
			cameraRotationSync = reader.ReadSingle();
			return;
		}
		int num = (int)reader.ReadPackedUInt32();
		if ((num & 1) != 0)
		{
			cameraRotationSync = reader.ReadSingle();
		}
	}
}
